assert.h
assert()
The assert.h
header file defines the macro assert()
, which is used at runtime to ensure that the program meets the specified conditions, and to terminate it with an error if it does not. This macro is often referred to as an "assert".
assert(PI > 3);
The above code verifies that the variable PI
is greater than 3 when the program reaches this line; if it is, the program will continue, otherwise it will terminate with an error message.
The assert()
macro takes an expression as an argument. If the expression is true (returns a non-zero value), assert()
does nothing and the program continues to run. If the expression is false (returns a zero value), assert()
reports an error, writing an error message to the standard error stream stderr
, showing the expression that did not pass, along with the name and line number of the file containing the expression. Finally, the abort()
function is called to terminate the program (the prototype of the abort()
function is in the stdlib.h
header file).
z = x * x - y * y;
assert(z >= 0);
The assert()
statement above is similar to the following code.
if (z < 0) {
puts("z less than 0");
abort();
}
If the assertion fails, the program will interrupt execution and the following prompt will be displayed.
Assertion failed: (z >= 0), function main, file /Users/assert.c, line 14.
The format of the error reported above is as follows.
Assertion failed: [expression], function [abc], file [xyz], line [nnn].
In the above code, the square bracketed parts are replaced with the actual data.
Using assert()
has several advantages: not only does it automatically identify the file and the line number in question, it also has a mechanism for turning assert()
on and off without changing the code. If you have confirmed that the program is OK and no further assertions are needed, define a macro NDEBUG
just before the #include <assert.h>
statement.
#define NDEBUG
#include <assert.h>
Then, recompile the program and the compiler will disable all assert()
statements in the file. If the program has problems again, you can remove this #define NDBUG
directive (or comment it out) and compile again, which re-enables the assert()
statement.
The disadvantage of assert()
is that it increases the runtime of the program because of the extra checks introduced.
static_assert()
C11 introduces the static assertion static_assert()
, which is used to make assertion judgements at the compile stage.
static_assert(constant-expression, string-literal);
static_assert()
takes two arguments, the first argument constant-expression
is a constant expression and the second argument string-literal
is a hint string. If the value of the first argument is false, a compile error is generated, and the second argument is the error message.
static_assert(sizeof(int) == 4, "64-bit code generation is not supported.");
The above code means that if the current computer's int
type is not equal to 4 bytes, it will compile with an error.
Note that static_assert()
only runs at the compile stage and cannot get the value of the variable. A static assertion of a variable will result in a compile error.
int positive(const int n) {
static_assert(n > 0, "value must > 0");
return 0;
}
The above code will cause a compile error because the value of the variable n
is not known at compile time.
The benefit of static_assert()
is to try to find the error at the compile stage and avoid reporting it again at runtime, saving development time. Also, some assert()
assertions are located within a function and will not report an error if the function is not executed, whereas static_assert()
will make the assertion judgement regardless of whether the function is executed or not. Finally, static_assert()
does not generate executable code, so it does not cause any runtime performance loss.